第一步是把昨天醜到爆炸的程式改好看一點!
經過一番查詢,我找到了 keys 這個函式,功能是將 Map 所有的 key 匯聚成 Set 型態並回傳
// Returns a read-only Set of all keys in this map.
abstract val keys: Set<K>
接下來我在 Set 形態中又找到了 elementAt 這個函式,由於 Set 沒有順序關係,所以功能是依照 存取的先後順序來讀取第 n 個值
// Returns an element at the given index or throws an IndexOutOfBoundsException if the index is out of bounds of this array.
fun <T> Iterable<T>.elementAt(index: Int): T
因為昨天甚麼 index、Number 之類的太容易搞混了,所以我有先修改一些變數名稱:
private val _questionBankHiragana: Map<String, String> = mapOf("a" to "あ","i" to "い","u" to "う","e" to "え","o" to "お",
"ka" to "か","ki" to "き","ku" to "く","ke" to "け","ko" to "こ",
"sa" to "さ","shi" to "し","su" to "す","se" to "せ","so" to "そ",
"ta" to "た","chi" to "ち","tsu" to "つ","te" to "て","to" to "と")
private var _question: String = ""
private val _choices: Array<String?> = arrayOfNulls<String>(5)
private var _ansNumber: Int = 0
再把 setPaper 那邊的程式碼整理一下,改名成 updateQuestion,變成下面這個樣子:
public fun updateQuestion(){
val mode = (1..2).random()
val correctAnsNumber = (0..getQuestionLastNumber()).random()
val keys:Set<String> = _questionBankHiragana.keys
_ansNumber = (1 .. 4).random()
if(mode == 1){ // 題目是 key,選項是 value
_question = keys.elementAt(correctAnsNumber)
_choices[_ansNumber] = _questionBankHiragana[_question]
}
else if(mode == 2){ // 題目是 value,選項是 key
_choices[_ansNumber] = keys.elementAt(correctAnsNumber)
_question = _questionBankHiragana[_choices[_ansNumber]].toString()
}
val otherChoice:Array<String?> = getOtherChoice(mode,correctAnsNumber,keys)
var count = 0
for (i in 0..3){
if(i == _ansNumber)
continue
_choices[i] = otherChoice[count]
count++
}
}
還要記得修一下 getOtherChoice 的程式碼,變成下面這個樣子:
public fun getOtherChoice(mode: Int, correctAnsNumber: Int, keys: Set<String>): Array<String?>{
val otherChoice: Array<String?> = arrayOfNulls<String>(3)
var count = 0
while(count <= 2){
var worngAnsNumber = (0..getQuestionLastNumber()).random()
if(worngAnsNumber==correctAnsNumber)
continue
if(mode==1){ // 題目是 key,選項是 value
otherChoice[count] = _questionBankHiragana[keys.elementAt(worngAnsNumber)]
}
else if(mode==2){ // 題目是 value,選項是 key
otherChoice[count] = keys.elementAt(worngAnsNumber)
}
count++
}
return otherChoice
}
記得先在主程式中宣告 Test
我們需要學一個酷東西叫做延遲,我希望當點擊選項後大概三秒鐘,才會跳轉到下一題,也方便之後顯示回答是否正確,延遲語法如下
Handler().postDelayed(Runnable {
// 延遲後要做的事寫在這裡
},3000); // 這裡寫想要延遲的秒數,單位是 ms
最後把 onCreateView 的程式改成這樣:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentHomeBinding.inflate(inflater,container,false)
val view = viewBinding.root
setPaper(viewBinding)
viewBinding.firstButton.setOnClickListener{
viewBinding.firstButton.setOnClickListener{
Handler().postDelayed(Runnable {
setPaper(viewBinding)
},3000);
}
}
viewBinding.secondButton.setOnClickListener{
Handler().postDelayed(Runnable {
setPaper(viewBinding)
},3000);
}
viewBinding.thirdButton.setOnClickListener{
Handler().postDelayed(Runnable {
setPaper(viewBinding)
},3000);
}
viewBinding.fouthButton.setOnClickListener{
Handler().postDelayed(Runnable {
setPaper(viewBinding)
},3000);
}
return view
}
我又多寫了一個 setpaper,用來呼叫 test 得到題目資料
public fun setPaper(viewBinding: FragmentHomeBinding){
test.updateQuestion()
viewBinding.textView2.text = test.getQusetion()
viewBinding.firstButton.text = test.getChoice(0)
viewBinding.secondButton.text = test.getChoice(1)
viewBinding.thirdButton.text = test.getChoice(2)
viewBinding.fouthButton.text = test.getChoice(3)
}
昨天的 bug 其實蠻多的,但在重新架構的時候大部分問題就被處理掉了;這邊跟大家講一個小知識,如果按下 RUN app 結果程式一直跳掉代表程式有問題,項是我剛剛在分配題目給 otherChoice的時候,好像有 overflow 的問題,然後改完就正常了,真開心!
下一篇我們來處理排版和偵測答案是否正確 ~
Kotlin 學習筆記(8)-集合函數
https://andyludeveloper.medium.com/kotlin-學習筆記-8-集合函數-2922bbf44b77
<>實現delay的效果-以及timer
https://lynn5133.pixnet.net/blog/post/459338761-<>實現delay的效果-以及timer
Android-用 Handler 製造出延遲( delay ) 發生的效果
https://brianchen85.blogspot.com/2014/12/android-handler-delay.html